package com.zhiyume.shiro;

import com.zhiyume.exception.AccountNotFoundException;
import com.zhiyume.exception.InactivePasswordException;
import com.zhiyume.exception.IncorrectCaptchaException;
import com.zhiyume.exception.IncorrectPasswordException;
import com.zhiyume.service.AdminService;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
 * 安全认证过滤器
 */
public class SecurityFilter extends FormAuthenticationFilter {
    private static Logger logger = LogManager
            .getLogger(SecurityFilter.class);
    @Autowired
    private AdminService userService;

    /**
     * 默认的验证码输入框标识
     */
    public static final String DEFAULT_CAPTCHA_PARAM = "captcha";

    /**
     * 默认登录后的转向逻辑（到登录前的界是否跳转面）
     */
    public static final boolean DEFAULT_REDIRECT_TO_SAVED_REQUEST = false;

    /**
     * 默认的编码方式
     */
    public static final String DEFAULT_CHARACTER_ENCODING = "UTF-8";

    /**
     * 验证码输入框标识
     */
    private String captchaParam = DEFAULT_CAPTCHA_PARAM;

    public String getCaptchaParam() {
        return captchaParam;
    }

    public void setCaptchaParam(String captchaParam) {
        this.captchaParam = captchaParam;
    }

    /**
     * 登录后的转向逻辑（是否跳转到登录前的界面）
     */
    private boolean redirectToSavedRequest = DEFAULT_REDIRECT_TO_SAVED_REQUEST;

    /**
     * 验证码的属性Key（用于从session中获取系统生成的验证码）
     */
    public static final String CAPTCHA_SESSION = "SECURITY.LOGIN.CAPTCHA";

    /**
     * 登录错误输入框元素名称
     */
    public static final String LOGIN_FAILED_ELEMENT = "SECURITY.LOGIN.FAILED.ELEMENT";

    /**
     * 登录错误提示信息
     */
    public static final String LOGIN_FAILED_MESSAGE = "SECURITY.LOGIN.FAILED.MESSAGE";

    /**
     * 根据登录信息，创建登录用户的token
     *
     * @param request
     * @param response
     * @return AuthenticationToken
     * */
   /* @Override
    protected AuthenticationToken createToken(ServletRequest request,
                                              ServletResponse response) {
        try {
            request.setCharacterEncoding(DEFAULT_CHARACTER_ENCODING);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        *//**获取userSeqId*//*
        String userName = request.getParameter("userName");
        String password ;
        *//**模拟登陆，从cookie 中回去用户信息*//*
        try {
             TAdminSys sysUser =  userService.selectAdminByUserName(userSeqId);
            if(sysUser == null){
                return new ShiroToken();
            }
            username = sysUser.getUserName();
            password = sysUser.getPassword();
        } catch (Exception e) {
            logger.error("认证出现异常");
            e.printStackTrace();
        }
        ShiroToken token = new ShiroToken(username, password);
        return token;
    }*/

    /**
     * 登录失败后的处理
     *
     * @param request
     *            ServletRequest对象
     * @param ae
     *            用户认证错误异常信息
     */
    @Override
    protected void setFailureAttribute(ServletRequest request,
                                       AuthenticationException ae) {
        String element = getUsernameParam();
        if (ae instanceof AccountNotFoundException) {
            element = getUsernameParam();
        }
        if (ae instanceof IncorrectPasswordException) {
            element = getPasswordParam();
        }
        if (ae instanceof IncorrectCaptchaException) {
            element = getCaptchaParam();
        }
        if (ae instanceof InactivePasswordException) {
            element = getPasswordParam();
        }
        request.setAttribute(LOGIN_FAILED_ELEMENT, element);
        request.setAttribute(LOGIN_FAILED_MESSAGE, ae.getMessage());
    }

    /**
     * 登录成功后的处理
     *
     * @param token
     *            登录用户的token
     * @param subject
     *            登录用户的Shiro信息
     * @param request
     *            ServletRequest对象
     * @param response
     *            ServletResponse对象
     * @return 是否登录成功
     * @throws Exception
     *             异常信息
     */
    @Override
    protected boolean onLoginSuccess(AuthenticationToken token,
                                     Subject subject, ServletRequest request, ServletResponse response)
            throws Exception {
        // 登录成功后，从session中去除校验码
        Session session = subject.getSession();
        session.removeAttribute(CAPTCHA_SESSION);

        // 触发执行鉴权方法
        AdminSecurityManager.isSessionUserAdminRole();
        if (redirectToSavedRequest) {
            return super.onLoginSuccess(token, subject, request, response);
        } else {
            WebUtils.issueRedirect(request, response, getSuccessUrl());
            return false;
        }
    }

    @Override
    public String getRememberMeParam() {
        // TODO Auto-generated method stub
        return super.getRememberMeParam();
    }

    @Override
    public String getFailureKeyAttribute() {
        // TODO Auto-generated method stub
        return super.getFailureKeyAttribute();
    }

    @Override
    protected String getUsername(ServletRequest request) {
        return WebUtils.getCleanParam(request, getUsernameParam());
    }

    @Override
    protected String getPassword(ServletRequest request) {
        return WebUtils.getCleanParam(request, getPasswordParam());
    }

    /**
     * 获取验证码标识
     *
     * @param request
     * @return String 验证码输入框标识
     * */
    protected String getCaptcha(ServletRequest request) {
        return WebUtils.getCleanParam(request, getCaptchaParam());
    }

    /**
     * 获取验证码输入框标识
     *
     * */
    protected String getCaptchaSession(ServletRequest request) {
        Subject subject = SecurityUtils.getSubject();
        Session session = subject.getSession();
        return (String) session.getAttribute(CAPTCHA_SESSION);
    }

}
